#include "ds1302.h"

extern struct TIMEData TimeData;

bsp_time_t ds1302_time;

uint16_t g_rtctick;

void delay_us(uint32_t us) {
    esp_rom_delay_us(us);
}
//配置dat口为输出口
void ds1302_dout_init(void)
{
    gpio_config_t DATAOUT_CFG = {
         .pin_bit_mask  = (1ULL<<DS1302_DAT), 
         .mode          = GPIO_MODE_OUTPUT,
         .pull_up_en    = GPIO_PULLUP_ENABLE,
         .pull_down_en  = GPIO_PULLDOWN_DISABLE,
         .intr_type     = GPIO_INTR_DISABLE
    };
    gpio_config(&DATAOUT_CFG);
}
//配置dat口为输入口
void ds1302_din_init(void)
{
    gpio_config_t DATAIN_CFG = {
         .pin_bit_mask  = (1ULL<<DS1302_DAT), 
         .mode          = GPIO_MODE_INPUT,
         .pull_up_en    = GPIO_PULLUP_ENABLE,
         .pull_down_en  = GPIO_PULLDOWN_DISABLE,
         .intr_type     = GPIO_INTR_DISABLE
    };
    gpio_config(&DATAIN_CFG);
}
//初始化gpio
void ds1302_gpio_init(void)
{
    //初始化RST引脚
    gpio_config_t RST_CFG = {
         .pin_bit_mask  = (1ULL<<DS1302_RST), 
         .mode          = GPIO_MODE_OUTPUT,
         .pull_up_en    = GPIO_PULLUP_ENABLE,
         .pull_down_en  = GPIO_PULLDOWN_DISABLE,
         .intr_type     = GPIO_INTR_DISABLE
    };
    gpio_config(&RST_CFG);

    //初始化CLK引脚
    gpio_config_t CLK_CFG = {
        .pin_bit_mask   =   (1ULL<<DS1302_CLK),          //配置引脚
        .mode           =   GPIO_MODE_OUTPUT,            //输出模式
        .pull_up_en     =   GPIO_PULLUP_ENABLE,         //不使能上拉
        .pull_down_en   =   GPIO_PULLDOWN_DISABLE,        //不使能下拉
        .intr_type      =   GPIO_INTR_DISABLE            //不使能引脚中断
    };
    gpio_config(&CLK_CFG);

    DS1302_CLK_L;
    DS1302_RST_L;

    ds1302_dout_init();
}
//发送一字节数据
void ds1302_send_byte(uint8_t _data)
{
    uint8_t data1 = _data;
    ds1302_dout_init();
    DS1302_CLK_L;
    for(uint8_t i = 0; i < 8; i++)
    {
        DS1302_CLK_L;
        if(data1 & 0x01){
            DS1302_DAT_H;delay_us(1000);
        }else{
            DS1302_DAT_L;delay_us(1000);
        }
        DS1302_CLK_H;
        data1 >>= 1;
    }

}
//写特定地址
void DS1302_Write_Reg (uint8_t _address , uint8_t _data)
{
    uint8_t data1 = _address;
    uint8_t data2 = _data;

    DS1302_RST_L;DS1302_CLK_L;delay_us(1000);
    // ds1302_dout_init();
    DS1302_RST_H;delay_us(1000);

    ds1302_send_byte(data1); 
    ds1302_send_byte(data2);
    DS1302_RST_L;DS1302_CLK_L;delay_us(1000);  
}
//读特定地址
uint8_t DS1302_Read_Reg(uint8_t _address)
{
    uint8_t data1 = _address;
    uint8_t recdata = 0;
    uint8_t retnum ;
    DS1302_RST_L;DS1302_CLK_L;delay_us(1000);
    DS1302_RST_H;delay_us(1000);
    ds1302_send_byte(data1);
    ds1302_din_init();//配置I/O口为输入
    delay_us(1000);
    for(uint8_t i = 0; i < 8; i ++)
    {
        delay_us(1000);
        recdata >>= 1;
        DS1302_CLK_H;delay_us(1000);
        DS1302_CLK_L;delay_us(1000);
        if(gpio_get_level(DS1302_DAT)){
            recdata = recdata | 0x80;
        }
    }
    delay_us(1000);
    DS1302_RST_L;DS1302_CLK_L;
    retnum = BCD_TO_DEC(recdata);
    return retnum;
}
//读取数据并返回
bsp_time_t DS1302_Read_Time()
{
    bsp_time_t read_time;
        read_time.second = DS1302_Read_Reg(0x81); //读秒
        read_time.minute = DS1302_Read_Reg(0x83); //读分
        read_time.hour = DS1302_Read_Reg(0x85);   //读时
        read_time.day = DS1302_Read_Reg(0x87);    //读日
        read_time.month = DS1302_Read_Reg(0x89);  //读月
        read_time.week = DS1302_Read_Reg(0x8B);   //读星期
        read_time.year = DS1302_Read_Reg(0x8D);   //读年
        return read_time;
}
//设定所有的时间，先定义一个结构体,然后调用这个函数
void ds1302_set_alltime(bsp_time_t set_time)
{
    uint8_t temp;
    DS1302_Write_Reg(0x8e, 0x00); //关闭写保护

    temp = DEC_TO_BCD(set_time.year);
    DS1302_Write_Reg(0x8c, temp);

    temp = DEC_TO_BCD(set_time.month);
    DS1302_Write_Reg(0x88, temp);

    temp = DEC_TO_BCD(set_time.week);
    DS1302_Write_Reg(0x8a, temp);

    temp = DEC_TO_BCD(set_time.day);
    DS1302_Write_Reg(0x86, temp);

    temp = DEC_TO_BCD(set_time.hour);
    DS1302_Write_Reg(0x84, temp);

    temp = DEC_TO_BCD(set_time.minute);
    DS1302_Write_Reg(0x82, temp);

    temp = DEC_TO_BCD(set_time.second);
    DS1302_Write_Reg(0x80, temp);

    DS1302_Write_Reg(0x8e, 0x80); //打开写保护
}